package com.cash.lemoloan.jsbridge;

import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.WebView;

import com.cash.lemoloan.jsbridge.Utils.JsonUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;


public class JavaScriptBridge {
    private WebView webView;
    private boolean isJsbReady;
    Map<String, Callback> jsCallbacks;
    Map<String, JSONObject> callJsFunctionQ;

    public static final String NAMESPACE = "__JavascriptBridge__";
    public static final String CALLBACK = "javascript:__JavascriptBridge__.javaCallback(\"%s\",\"%s\", %s)";
    public static final String NOEXIT = "javascript:__JavascriptBridge__.javaCallback(\"%s\", {\"methodName\":\"%s\",\"resCode\":\"10000\",\"resMsg\":\"function no exit\"})";
    public static final String CALLJS = "javascript:__JavascriptBridge__.jsHandler(\"%s\",\"%s\",%s)";

    public JavaScriptBridge(WebView webView) {
        this.webView = webView;
        jsCallbacks = new HashMap<>();
        callJsFunctionQ = new HashMap<>();
        webView.addJavascriptInterface(new JavaScriptInterface(),NAMESPACE);
    }

    public synchronized void callJsFunction(String functionName, Bundle params, Callback callBackFunction){
        callJsFunction(functionName, JsonUtil.bundleToJSON(params),callBackFunction);
    }

    /**
     * 调用js方法
     * @param functionName
     * @param params
     * @param callBackFunction
     */
    public synchronized void callJsFunction(String functionName, JSONObject params, Callback callBackFunction){
        try{
            if (TextUtils.isEmpty(functionName)){
                return;
            }
            String id = "";
            if (callBackFunction != null) {
                id = String.valueOf(System.currentTimeMillis());
                jsCallbacks.put(id, callBackFunction);
            }
            if (!isJsbReady){
                callJsFunctionQ.put(functionName,params);
                return;
            }
            loadUrl(String.format(CALLJS,functionName,id,params));
        }catch (Exception e){
        }
    }

    private void loadUrl(final String url){
        JsBridgeApplication.getMainHandler().post(new Runnable() {
            @Override
            public void run() {
                webView.loadUrl(url);
            }
        });
    }

    /**
     * 调用js方法
     * @param functionName
     */
    public synchronized void callJsFunction(String functionName){
        callJsFunction(functionName,new JSONObject());
    }

    /**
     * 调用js方法
     * @param functionName
     * @param params
     */
    public synchronized void callJsFunction(String functionName, JSONObject params){
        callJsFunction(functionName,params,null);
    }

    /**
     * 调用js方法
     * @param functionName
     * @param params
     */
    public synchronized void callJsFunction(String functionName, Bundle params){
        callJsFunction(functionName,JsonUtil.bundleToJSON(params),null);
    }

    class JavaScriptInterface {

        @android.webkit.JavascriptInterface
        public String requireSync(String functionName, String params){
            isJsbReady = true;
            synchronized (JavaScriptBridge.this){
                JSONObject r = new JSONObject();
                try {
                    r.put("methodName",functionName);
                    if (TextUtils.isEmpty(functionName)){
                        r.put("resCode","10000");
                        r.put("resMsg","method no exit");
                        return r.toString();
                    }
                    FunctionSync javaSyncFunction = FunManager.getFunctionSync(functionName);
                    if (javaSyncFunction == null){
                        r.put("resCode","10000");
                        r.put("resMsg","method no exit");
                        return r.toString();
                    }
                    JSONObject p  = JsonUtil.loadJSON(params);
                    JSONObject result = javaSyncFunction.onHandle(p);
                    if (result != null) r = result;
                    r.put("resCode","0000");
                    r.put("resMsg","success");
                } catch (JSONException j){

                }
                return r.toString();
            }
        }

        @android.webkit.JavascriptInterface
        public void requireAsync(final String functionName, final String reqId, final String params){
            isJsbReady = true;
            BackgroundFunctionTask.runBackground(new Runnable() {
                @Override
                public void run() {
                    try{
                        String noExit =  String.format(NOEXIT,reqId,functionName);
                        if (TextUtils.isEmpty(functionName)){
                            loadUrl(noExit);
                            return;
                        }
                        Function javaAsyncFunction = FunManager.getFunction(functionName);
                        if (null == javaAsyncFunction){
                            loadUrl(noExit);
                            return;
                        }
                        JSONObject p = JsonUtil.loadJSON(params);
                        javaAsyncFunction.onHandle(p, new Callback() {
                            @Override
                            public void onComplete(JSONObject data) {
                                data = JsonUtil.putObject(data,"reqId",reqId);
                                String returnUrl = String.format(CALLBACK,functionName,reqId, data == null ? "" : data.toString());
                                loadUrl(returnUrl);
                            }
                        });}catch (Exception e){
                    }
                }
            });
        }

        @android.webkit.JavascriptInterface
        public void jsCallback(String requestcode, String jsonResult){
            isJsbReady = true;
            Callback callBack = jsCallbacks.remove(requestcode);
            if (callBack == null){
                return;
            }
            callBack.onComplete(JsonUtil.loadJSON(jsonResult));
        }




    }
}